package org.luxor.cloud.gateway.config;

import org.luxor.cloud.gateway.component.GlobalExceptionHandler;
import org.luxor.cloud.gateway.component.route.DynamicRouteDefinitionRepository;
import org.luxor.cloud.gateway.component.trace.TraceGlobalFilter;
import org.luxor.cloud.gateway.component.trace.TraceRegistry;
import org.luxor.cloud.gateway.service.DynamicRouteService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.web.ResourceProperties;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.web.reactive.error.ErrorAttributes;
import org.springframework.cloud.gateway.config.GatewayAutoConfiguration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.web.reactive.result.view.ViewResolver;

import java.util.Collections;
import java.util.List;

/**
 * 网关自定义配置
 *
 * @author Mr.Yan  @date: 2020/10/21
 * @see GatewayAutoConfiguration 默认网关配置
 */
@Configuration
public class GatewayRouteConfiguration {

    /**
     * 从"存储器"读取动态路由配置
     */
    @Bean
    public DynamicRouteDefinitionRepository dynamicRouteDefinitionRepository(
            DynamicRouteService dynamicRouteService) {
        return new DynamicRouteDefinitionRepository(dynamicRouteService);
    }

    /**
     * 全局统一的异常处理器
     */
    @Bean
    @Order(-1)
    public GlobalExceptionHandler globalExceptionHandler(
            ObjectProvider<List<ViewResolver>> viewResolversProvider, ErrorAttributes errorAttributes,
            ServerProperties serverProperties, ResourceProperties resourceProperties,
            ServerCodecConfigurer serverCodecConfigurer, ApplicationContext applicationContext) {

        GlobalExceptionHandler exceptionHandler = new GlobalExceptionHandler(errorAttributes, resourceProperties,
                serverProperties.getError(), applicationContext);

        List<ViewResolver> viewResolvers = viewResolversProvider.getIfAvailable(() -> Collections.emptyList());
        exceptionHandler.setViewResolvers(viewResolvers);
        exceptionHandler.setMessageWriters(serverCodecConfigurer.getWriters());
        exceptionHandler.setMessageReaders(serverCodecConfigurer.getReaders());
        return exceptionHandler;
    }

    /**
     * 访问记录跟踪过滤器
     */
    @Bean
    public TraceGlobalFilter traceGlobalFilter() {
        final Logger logger = LoggerFactory.getLogger(TraceRegistry.class);

        return new TraceGlobalFilter(tags -> {
            if (logger.isDebugEnabled()) {
                StringBuffer log = new StringBuffer("\r\n=====================================================\r\n");
                tags.forEach(tag -> log.append(tag.getKey()).append(": ").append(tag.getValue()).append("\r\n"));
                log.append("=====================================================\r\n");
                logger.debug(log.toString());
            }
        });
    }

}
